#pragma once

#include <memory>
#include <functional>

#include "fields.hpp"

namespace JsonRpc
{
    class BaseMessage
    {
    public:
        using ptr = std::shared_ptr<BaseMessage>;

        virtual ~BaseMessage() {}
        virtual void setMType(MType mtype) { _mtype = mtype; }
        virtual MType Mtype() { return _mtype; }
        virtual void setId(const std::string &id) { _rid = id; }
        virtual std::string rid() { return _rid; }
        virtual std::string serialize() = 0;
        virtual bool deserialize(const std::string &msg) = 0;
        virtual bool check() = 0; //?

    protected:
        MType _mtype;
        std::string _rid;
    };

    class BaseBuffer
    {
    public:
        using ptr = std::shared_ptr<BaseBuffer>;

        virtual ~BaseBuffer(){}
        virtual size_t readableSize() = 0;
        virtual int32_t peekInt32() = 0;
        virtual void retrieveInt32() = 0;
        virtual int32_t readInt32() = 0;
        virtual std::string retrieveAsString(size_t len) = 0;
    };

    class BaseProtocol //应用层协议
    {
    public:
        using ptr = std::shared_ptr<BaseProtocol>;

        virtual ~BaseProtocol(){}
        virtual bool canProcessed(const BaseBuffer::ptr &buf) = 0; //?
        virtual bool onMessage(const BaseBuffer::ptr &buf, BaseMessage::ptr &msg) = 0; //?
        virtual std::string serialize(const BaseMessage::ptr &msg) = 0; //?
    };

    
    class BaseConnection //服务器所属?
    {
    public:
        using ptr = std::shared_ptr<BaseConnection>;

        virtual ~BaseConnection(){}
        virtual void send(const BaseMessage::ptr &msg) = 0;
        virtual void shutdown() = 0;
        virtual bool connected() = 0;
    };

    using ConnectionCallBack = std::function<void(const BaseConnection::ptr &)>;
    using CloseCallBack = std::function<void(const BaseConnection::ptr &)>;
    using MessageCallBack = std::function<void(const BaseConnection::ptr &, BaseMessage::ptr &)>; //?

    class BaseServer
    {
    public:
        using ptr = std::shared_ptr<BaseServer>;
        
        virtual ~BaseServer() {}
        virtual void setConnectionCallBack(const ConnectionCallBack &cb) { _cb_connection = cb; }
        virtual void setCloseCallBack(const CloseCallBack &cb) { _cb_close = cb; }
        virtual void setMessageCallBack(const MessageCallBack &cb) { _cb_message = cb; }
        virtual void start() = 0;

    protected:
        ConnectionCallBack _cb_connection;
        CloseCallBack _cb_close;
        MessageCallBack _cb_message;
    };

    class BaseClient
    {
    public:
        virtual ~BaseClient() {}
        virtual void setConnectionCallBack(const ConnectionCallBack &cb) { _cb_connection = cb; }
        virtual void setCloseCallBack(const CloseCallBack &cb) { _cb_close = cb; }
        virtual void setMessageCallBack(const MessageCallBack &cb) { _cb_message = cb; }
        virtual void connect() = 0;
        virtual bool connected() = 0;
        virtual BaseConnection::ptr connection() = 0;
        virtual void send(const BaseMessage::ptr &msg) = 0;
        virtual void shutdown() = 0;

    protected:
        ConnectionCallBack _cb_connection;
        CloseCallBack _cb_close;
        MessageCallBack _cb_message;
    };
}